package com.jc.auth.domain.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.jc.auth.common.enums.AuthUserStatusEnum;
import com.jc.auth.common.enums.IsDeletedFlagEnum;
import com.jc.auth.domain.constants.AuthConstant;
import com.jc.auth.domain.convert.AuthUserBOConverter;
import com.jc.auth.domain.entity.AuthUserBO;
import com.jc.auth.domain.redis.RedisUtil;
import com.jc.auth.domain.service.AuthUserDomainService;
import com.jc.auth.infra.basic.entity.*;
import com.jc.auth.infra.basic.service.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: ASL_ly
 * @Package: com.jc.auth.domain.service.impl
 * @Project: jc-club
 * @Date: 2024/10/28  22:53
 */
@Service
@Slf4j
public class AuthUserDomainServiceImpl implements AuthUserDomainService {
    @Resource
    private AuthUserService authUserService;
    @Resource
    private AuthUserRoleService authUserRoleService;
    @Resource
    private AuthRoleService authRoleService;
    @Resource
    private AuthPermissionService authPermissionService;
    @Resource
    private AuthRolePermissionService authRolePermissionService;
    @Resource
    private RedisUtil redisUtil;

    /**
     * 用户注册
     *
     * @param authUserBO
     * @return
     */
    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("userController.register.bo:{}", JSON.toJSONString(authUserBO));
        }
        //校验用户是否存在
        AuthUser existAuthUser = new AuthUser();
        existAuthUser.setUserName(authUserBO.getUserName());
        List<AuthUser> existUser = authUserService.queryByCondition(existAuthUser);
        if(existUser.size() > 0){
            return true;
        }
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToUser(authUserBO);
        if(StringUtils.isNotBlank(authUser.getPassword())){
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(), AuthConstant.SALT));
        }
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.code);
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        Integer count = authUserService.insert(authUser);
        //建立用户角色初步关联
        //查询普通用户角色id
        AuthRole authRole = AuthRole.builder()
                .roleKey(AuthConstant.NORMAL_USER)
                .isDeleted(IsDeletedFlagEnum.UN_DELETED.code)
                .build();
        AuthRole resultRole = authRoleService.queryByCondition(authRole).get(0);
        Long roleId = resultRole.getId();
        //插入用户角色关联表
        AuthUserRole authUserRole = AuthUserRole.builder()
                .userId(authUser.getId())
                .roleId(roleId)
                .isDeleted(IsDeletedFlagEnum.UN_DELETED.code)
                .build();
        authUserRoleService.insert(authUserRole);
        //将用户角色信息插入到redis中
        String roleKey = redisUtil.buildKey(AuthConstant.authRolePrefix, authUser.getUserName());
        List<AuthRole> authRoleList = new LinkedList<>();
        authRoleList.add(authRole);
        redisUtil.set(roleKey, new Gson().toJson(authRoleList));

        //将用户权限信息插入到redis中
        //先查role_permission查得角色所拥有的权限的id
        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        List<AuthRolePermission> authRolePermissionList = authRolePermissionService.queryByCondition(authRolePermission);
        List<Long> permissionIdList = authRolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId).collect(Collectors.toList());
        //在查auth_permission表查得权限信息
        List<AuthPermission> authPermissionList = authPermissionService.queryByPermissionIdList(permissionIdList);
        String permissionKey = redisUtil.buildKey(AuthConstant.authPermissionPrefix, authUser.getUserName());
        redisUtil.set(permissionKey,new Gson().toJson(authPermissionList));

        return count > 0;
    }

    /**
     * 修改用户信息
     * @param authUserBO
     * @return
     */
    @Override
    public Boolean update(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("userController.update.bo:{}", JSON.toJSONString(authUserBO));
        }
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToUser(authUserBO);
        Integer count = authUserService.update(authUser);
        return count > 0;
        //要把当前用户的角色和权限都刷到redis里

    }

    /**
     * 删除用户
     * @param authUserBO
     * @return
     */
    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("userController.delete.bo:{}", JSON.toJSONString(authUserBO));
        }
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToUser(authUserBO);
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.code);
        Integer count = authUserService.update(authUser);
        return count > 0;
    }

    /**
     * 用户登录
     * @param validCode
     * @return
     */

    @Override
    public SaTokenInfo doLogin(String validCode) {
        String loginKey = redisUtil.buildKey(AuthConstant.LOGIN_PREFIX, validCode);
        String openId = redisUtil.get(loginKey);
        if(StringUtils.isBlank(openId)){
            return null;
        }
        AuthUserBO authUserBO = new AuthUserBO();
        authUserBO.setUserName(openId);
        this.register(authUserBO);
        StpUtil.login(openId);
        SaTokenInfo saTokenInfo =StpUtil.getTokenInfo();
        return saTokenInfo;

    }

    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        List<AuthUser> userList = authUserService.queryByCondition(authUser);
        if(CollectionUtils.isEmpty(userList)){
            return new AuthUserBO();
        }
        AuthUser user = userList.get(0);
        AuthUserBO userInfo = AuthUserBOConverter.INSTANCE.convertUserToBO(user);
        return userInfo;
    }
}
